home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Development Tools & Languages / AppsToGo / DTS.Lib / Help.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  9.9 KB  |  405 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        Help.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19. /* This file contains some sample code for handling dynamic balloon help.  The
  20. ** assumption here is that you used the AppsToGo program editor to add controls
  21. ** to the content of a window that have balloon help assigned to them. */
  22.  
  23.  
  24.  
  25. /*****************************************************************************/
  26.  
  27.  
  28.  
  29. #include "DTS.Lib2.h"
  30. #include "DTS.Lib.protos.h"
  31.  
  32. #ifndef __BALLOONS__
  33. #include <Balloons.h>
  34. #endif
  35.  
  36. #ifndef __PROCESSES__
  37. #include <Processes.h>
  38. #endif
  39.  
  40. #ifndef __RESOURCES__
  41. #include <Resources.h>
  42. #endif
  43.  
  44. #ifndef __UTILITIES__
  45. #include "Utilities.h"
  46. #endif
  47.  
  48. #ifdef powerc
  49. #pragma options align=mac68k
  50. #endif
  51. typedef struct {
  52.     short    helpVers;
  53.     long    options;
  54.     short    procID;
  55.     short    variantForTip;
  56.     short    numMessages;
  57.     short    itemSize;
  58.     short    itemType[1];
  59. } hrctRec;
  60. typedef hrctRec *hrctRecPtr, **hrctRecHndl;
  61. #ifdef powerc
  62. #pragma options align=reset
  63. #endif
  64.  
  65. extern short    gQuickBalloons;
  66.  
  67. Boolean            gHaveQuickBalloon;
  68. PicHandle        gPicBalloon;
  69.  
  70. HMMessageRecord    gHelpMessage;
  71. Rect            gHelpMessageRct;
  72. ControlHandle    gHelpMessageCtl;
  73. WindowPtr        gHelpWithWindow;
  74.  
  75. extern short    gTECtl;
  76.  
  77. ControlHandle    ControlBalloonMessage(WindowPtr window, Point mouseLoc, HMMessageRecord *msg, Rect *msgRct,
  78.                                       short *pos, short *hrctID, short *itemID);
  79.  
  80.  
  81.  
  82. /*****************************************************************************/
  83. /*****************************************************************************/
  84.  
  85. #ifdef applec
  86. #pragma segment ATGCtlHandler
  87. #endif
  88.  
  89. /*****************************************************************************/
  90. /*****************************************************************************/
  91.  
  92.  
  93.  
  94. Boolean    ControlBalloonHelp(WindowPtr window, short modifiers, Point mouseLoc)
  95. {
  96.     WindowPtr                ww;
  97.     ProcessSerialNumber        cpsn, fpsn;
  98.     ControlHandle            ctl;
  99.     short                    hrctID, itemID, pos;
  100.     Boolean                    procsSame;
  101.     HMMessageRecord            message, msg;
  102.     Rect                    messageRct;
  103.  
  104. #ifndef powerc
  105.     if (gSystemVersion < 0x0700)
  106.         if (!gQuickBalloons)
  107.             return(false);
  108. #endif
  109.  
  110.     if (gSystemVersion >= 0x0700) {
  111.         if (!window) {
  112.             if (gHelpMessage.hmmHelpType) HMRemoveBalloon();
  113.             gHelpMessage.hmmHelpType = 0;
  114.         }
  115.         if (gQuickBalloons) {
  116.             if ((modifiers & gQuickBalloons) == gQuickBalloons) {
  117.                 if (!HMGetBalloons())
  118.                     HMSetBalloons(gHaveQuickBalloon = true);
  119.             }
  120.             else {
  121.                 if (gHaveQuickBalloon) {
  122.                     if (HMGetBalloons()) {
  123.                         HMRemoveBalloon();
  124.                         HMSetBalloons(false);
  125.                     }
  126.                     gHaveQuickBalloon = false;
  127.                     gHelpMessage.hmmHelpType = 0;
  128.                 }
  129.             }
  130.         }
  131.         if (!window) return(false);
  132.     }
  133. #ifndef powerc
  134.     else {
  135.         if (!window) {
  136.             gHelpMessage.hmmHelpType = 0;
  137.             return(false);
  138.         }
  139.         gHaveQuickBalloon = ((modifiers & gQuickBalloons) == gQuickBalloons) ? true : false;
  140.         if (!gHaveQuickBalloon) {
  141.             gHelpMessage.hmmHelpType = 0;
  142.             return(false);
  143.         }
  144.     }
  145. #endif
  146.  
  147.     if (gSystemVersion >= 0x0700) {
  148.         if (!HMGetBalloons()) {
  149.             gHelpMessage.hmmHelpType = 0;
  150.             return(false);
  151.         }        /* Balloons have been turned off. */
  152.  
  153.         HMGetBalloonWindow(&ww);
  154.         if (!ww)
  155.             gHelpMessage.hmmHelpType = 0;
  156.                 /* There is no balloon currently, so there is no last message. */
  157.     }
  158. #ifndef powerc
  159.     else {
  160.         if (!GetNextWindow(nil, '6hlp'))
  161.             gHelpMessage.hmmHelpType = 0;
  162.     }
  163. #endif
  164.  
  165.     if (gSystemVersion >= 0x0700) {
  166.         GetCurrentProcess(&cpsn);
  167.         GetFrontProcess(&fpsn);
  168.         SameProcess(&cpsn, &fpsn, &procsSame);
  169.         if (!procsSame) {
  170.             gHelpMessage.hmmHelpType = 0;
  171.             return(false);
  172.         }        /* We aren't the front process, so leave. */
  173.     }
  174. #ifndef powerc
  175.     else {
  176.         if (gInBackground) {
  177.             gHelpMessage.hmmHelpType = 0;
  178.             return(false);
  179.         }
  180.     }
  181. #endif
  182.  
  183.     if (!GetWRefCon(window)) {
  184.         gHelpMessage.hmmHelpType = 0;
  185.         return(false);
  186.     }
  187.  
  188.     ctl = ControlBalloonMessage(window, mouseLoc, &message, &messageRct, &pos, &hrctID, &itemID);
  189.  
  190.     if (message.hmmHelpType) {
  191.         if (!EqualRect(&gHelpMessageRct, &messageRct))
  192.             gHelpMessage.hmmHelpType = -1;
  193.         if (!EqualData(&gHelpMessage, &message, sizeof(message))) {        /* If new balloon... */
  194.             gHelpMessage    = message;
  195.             gHelpMessageRct = messageRct;
  196.             gHelpMessageCtl = ctl;
  197.             gHelpWithWindow = window;
  198.             if (gSystemVersion >= 0x0700) {
  199.                 msg = message;
  200.                 if (message.hmmHelpType == khmmTERes) {
  201.                     if (gPicBalloon) KillPicture(gPicBalloon);
  202.                     gPicBalloon = BalloonText2PICT(window, &message);
  203.                     if (gPicBalloon) {
  204.                         msg.hmmHelpType = khmmPictHandle;
  205.                         msg.u.hmmPictHandle = gPicBalloon;
  206.                     }
  207.                 }
  208.                 HMShowBalloon(&msg, mouseLoc, &messageRct, nil, 0, pos, kHMRegularWindow);
  209.             }
  210. #ifndef powerc
  211.             else {
  212.                 if (gHaveQuickBalloon) {
  213.                     ww = GetNextWindow(nil, '6hlp');
  214.                     if (ww) {
  215.                         gHelpMessage.hmmHelpType = 0;
  216.                         return(false);
  217.                     }
  218.                     if (NewDocumentWindow(nil, '6hlp', false)) {
  219.                         gHelpMessage.hmmHelpType = 0;
  220.                         return(false);
  221.                     }
  222.                 }
  223.             }
  224. #endif
  225.         }
  226.         return(true);
  227.     }
  228.     else {
  229.         if (gSystemVersion >= 0x0700) {
  230.             if (gHelpMessage.hmmHelpType)
  231.                 HMRemoveBalloon();
  232.         }
  233.         gHelpMessage.hmmHelpType = 0;
  234.         if (gPicBalloon) {
  235.             KillPicture(gPicBalloon);
  236.             gPicBalloon = nil;
  237.         }
  238.     }
  239.  
  240.     return(false);
  241. }
  242.  
  243.  
  244.  
  245. /*****************************************************************************/
  246.  
  247.  
  248.  
  249. ControlHandle    ControlBalloonMessage(WindowPtr window, Point mouseLoc, HMMessageRecord *msg, Rect *msgRct,
  250.                                       short *pos, short *hrctID, short *itemID)
  251. {
  252.     Point                pt;
  253.     WindowPtr            oldPort;
  254.     ControlStyleInfo    cinfo;
  255.     Rect                rct;
  256.     short                charsUsed, i, j, cv, strNumID, strNumIndx;
  257.     long                ofst;
  258.     ControlHandle        ctl;
  259.     char                *cptr;
  260.     hrctRecHndl            hrct;
  261.     Ptr                    ptr;
  262.     static short        position[4] = {5, 6, 2, 1};
  263.  
  264.     msg->hmmHelpType  = 0;
  265.     *hrctID = *itemID = 0;
  266.  
  267.     GetPort(&oldPort);
  268.     SetPort(window);
  269.     pt = mouseLoc;
  270.     GlobalToLocal(&pt);
  271.     SetPort(oldPort);
  272.  
  273.     if (!WhichControl(pt, 0, window, &ctl)) return(nil);
  274.     if (!GetControlStyle(ctl, &cinfo))      return(nil);
  275.  
  276.     *msgRct = (*ctl)->contrlRect;
  277.     rct = (*(window->visRgn))->rgnBBox;
  278.     SectRect(&rct, msgRct, msgRct);
  279.     if (!PtInRect(pt, msgRct)) return(nil);
  280.  
  281.     cptr = (char *)cinfo.balloonHelp;
  282.     p2c((StringPtr)cptr);
  283.     if (!(*hrctID = c2dec(cptr, &charsUsed))) return(nil);
  284.     cptr += (charsUsed + 1);
  285.  
  286.     *itemID = c2dec(cptr, &charsUsed);
  287.     cptr += charsUsed;
  288.  
  289.     if (!(hrct = (hrctRecHndl)GetResource('hrct', *hrctID))) return(nil);
  290.  
  291.     if (*cptr == ',') {                                    /* If entry for inactive control... */
  292.         i = c2dec(++cptr, &charsUsed);
  293.         cptr += charsUsed;
  294.         if ((*ctl)->contrlHilite == 255) *itemID = i;    /* If control inactive... */
  295.     }
  296.  
  297.     while (*cptr == ':') {
  298.         cv = c2dec(++cptr, &charsUsed);
  299.         cptr += charsUsed;
  300.         i = j = c2dec(++cptr, &charsUsed);
  301.         cptr += charsUsed;
  302.         if (*cptr == ',') {                                    /* If entry for inactive control... */
  303.             j = c2dec(++cptr, &charsUsed);
  304.             cptr += charsUsed;
  305.         }
  306.         if (cv == (*ctl)->contrlValue) {
  307.             if (!(*ctl)->contrlHilite)       *itemID = i;    /* If control active... */
  308.             if ((*ctl)->contrlHilite == 255) *itemID = j;    /* If control inactive... */
  309.             break;
  310.         }
  311.     }
  312.  
  313.     if (!(hrct = (hrctRecHndl)GetResource('hrct', *hrctID))) return(nil);
  314.     if (*itemID > (*hrct)->numMessages)                      return(nil);
  315.     if (!*itemID)                                            return(nil);
  316.  
  317.     ofst = offsetof(hrctRec,itemSize);
  318.     for (i = 1; i < *itemID; ++i) {
  319.         ptr = (Ptr)*hrct;
  320.         ofst += *(short *)(ptr + ofst);
  321.     }
  322.     ofst += sizeof(short);                            /* Point to item type. */
  323.  
  324.     SetMem(msg, 0, sizeof(HMMessageRecord));        /* Clean out structure for compare purposes. */
  325.     ptr = (Ptr)*hrct;
  326.     msg->hmmHelpType = *(short *)(ptr + ofst);
  327.     ofst += sizeof(short);
  328.     ofst += (sizeof(Point) + sizeof(Rect));            /* Skip 'hrct' tip and rect. */
  329.     switch (msg->hmmHelpType) {
  330.         case kHMStringItem:
  331.             pcpy((StringPtr)msg->u.hmmString, (StringPtr)(ptr + ofst));
  332.             break;
  333.         case kHMPictItem:
  334.             msg->u.hmmPict = *(short *)(ptr + ofst);
  335.             break;
  336.         case kHMStringResItem:
  337.             strNumID = *(short *)(ptr + ofst);
  338.             ofst += sizeof(short);
  339.             strNumIndx = *(short *)(ptr + ofst);
  340.             msg->u.hmmStringRes.hmmResID = strNumID;
  341.             msg->u.hmmStringRes.hmmIndex = strNumIndx;
  342.             break;
  343.         case kHMTEResItem:
  344.             msg->u.hmmTERes = *(short *)(ptr + ofst);
  345.             break;
  346.         case kHMSTRResItem:
  347.             msg->u.hmmSTRRes = *(short *)(ptr + ofst);
  348.             break;
  349.     }
  350.  
  351.     LocalToGlobalRect(msgRct);
  352.     *pos = (mouseLoc.v > (msgRct->top + msgRct->bottom) / 2) ? 2 : 0;
  353.     if (mouseLoc.h > (msgRct->left + msgRct->right) / 2)
  354.         ++*pos;
  355.  
  356.     *pos = position[*pos];
  357.     return(ctl);
  358. }
  359.  
  360.  
  361.  
  362. /*****************************************************************************/
  363.  
  364.  
  365.  
  366. PicHandle    BalloonText2PICT(WindowPtr window, HMMessageRecord *msg)
  367. {
  368.     Rect            rct, **rh;
  369.     Handle            txt;
  370.     StScrpHandle    stl;
  371.     TEHandle        te;
  372.     PicHandle        pic;
  373.     short            ofst;
  374.     OSErr            err;
  375.  
  376.     if (msg->hmmHelpType != kHMTEResItem) return(nil);
  377.     if (!(rh  =      (Rect **)Get1Resource('RECT', msg->u.hmmTERes))) return(nil);
  378.     if (!(txt =               Get1Resource('TEXT', msg->u.hmmTERes))) return(nil);
  379.     if (!(stl = (StScrpHandle)Get1Resource('styl', msg->u.hmmTERes))) return(nil);
  380.  
  381.     rct = **rh;
  382.  
  383.     err = CTENew(gTECtl, false, window, &te, &rct, &rct, &rct, &rct, 32000, (cteNoBorder, cteStyledTE));
  384.     if (err) return(nil);
  385.  
  386.     DetachResource(txt);
  387.     DetachResource((Handle)stl);
  388.     DisposeHandle(CTESwapText(te, txt, stl, false));
  389.     DisposeHandle((Handle)stl);
  390.  
  391.     pic = OpenPicture(&rct);
  392.     if (pic) {
  393.         ofst = 0;
  394.         CTEPrint(te, &ofst, &rct);        /* The bottom of rct is now calculated, returned in rct.bottom. */
  395.         ClosePicture();
  396.         (*pic)->picFrame.bottom = rct.bottom;
  397.     }
  398.  
  399.     DisposeControl(CTEViewFromTE(te));
  400.     return(pic);
  401. }
  402.  
  403.  
  404.  
  405.